package sheeps

/*
#cgo LDFLAGS: -ldl -lm
#ifndef __HEAD_FILE__
#define __HEAD_FILE__
#include <stdio.h>
#include <dlfcn.h>

typedef void* HSOCKET;
typedef unsigned char PROTOCOL;

typedef void 		(*TaskUserLog)(void* proto, unsigned char level, const char* fmt, ...);
typedef long long 	(*Microsecond)();
typedef void		(*UserActiveTimeOutStop)(void* proto, int time);

typedef const char*	(*ConfigGetString)(const char* section, const char* key, const char* def);
typedef int			(*ConfigGetNumber)(const char* section, const char* key, int def);
typedef char		(*ConfigGetBool)(const char* section, const char* key, char def);

typedef HSOCKET	(*SocketConnect)(void* proto, const char* ip, int port, PROTOCOL protocol);
typedef char	(*SocketSend)(void* proto, HSOCKET hsock, const char* data, int len);
typedef char	(*SocketClose)(void* proto, HSOCKET hsock);

typedef void	(*HsocketPeerAddr)(HSOCKET hsock, char* ip, size_t ipsz, int* port);
typedef void	(*HsocketLocalAddr)(HSOCKET hsock, char* ip, size_t ipsz, int* port);
typedef void	(*HsocketPeerAddrSet)(HSOCKET hsock, const char* ip, int port);
typedef int		(*GetHostByName)(const char* name, const char* ip , size_t size);

typedef int		(*HsocketKcpCreate)(HSOCKET hsock, int conv, int mode);
typedef void	(*HsocketKcpNodelay)(HSOCKET hsock, int nodelay, int interval, int resend, int nc);
typedef void	(*HsocketKcpWndsize)(HSOCKET hsock, int sndwnd, int rcvwnd);
typedef int		(*HsocketKcpGetConv)(HSOCKET hsock);
typedef int		(*HsocketKcpDebug)(HSOCKET hsock, char* buf, int size);

typedef char	(*PlayStop)(void* proto, const char* fmt, ...);
typedef void 	(*PlayPause)(void* proto);
typedef void 	(*PlayNormal)(void* proto);
typedef void 	(*PlayFast)(void* proto, char fast);
typedef int		(*PlayStep)(void* proto);
typedef int		(*PlayStepSession)(void* proto);
typedef char* 	(*PlayStepNote)(void* proto);
typedef void 	(*PlayBack)(void* proto, int index);
typedef char	(*PlayAction)(void* proto, int action);
typedef void 	(*PlayNoStop)(void* proto);
typedef int		(*PlayOver)(void* proto);

typedef void	(*ReportOnline)(void* proto);
typedef void	(*ReportOffline)(void* proto);
typedef void 	(*ReportCounter)(void* proto, const char* key, int val, int stype, int space_time);
typedef void 	(*ReportApiResponse)(void* proto, const char* api, int response_time);
typedef void 	(*ReportApiSend)(void* proto, const char* api, int flow, int count);
typedef void 	(*ReportApiRecv)(void* proto, const char* api, int flow, int count);
typedef void	(*ReportOverMessage)(void* proto, const char* msg);

TaskUserLog				abi_Log;
Microsecond				abi_Microsecond;
UserActiveTimeOutStop	abi_UserActiveTimeOutStop

ConfigGetString			abi_ConfigGetString;
ConfigGetNumber			abi_ConfigGetNumber;
ConfigGetBool			abi_ConfigGetBool;

SocketConnect			abi_SocketConnect;
SocketSend				abi_SocketSend;
SocketClose				abi_SocketClose;

HsocketPeerAddr			abi_HsocketPeerAddr;
HsocketPeerAddrSet		abi_HsocketPeerAddrSet;
HsocketLocalAddr		abi_HsocketLocalAddr;
GetHostByName			abi_GetHostByName;

HsocketKcpCreate		abi_HsocketKcpCreate;
HsocketKcpNodelay		abi_HsocketKcpNodelay;
HsocketKcpWndsize		abi_HsocketKcpWndsize;
HsocketKcpGetConv		abi_HsocketKcpGetConv;
HsocketKcpDebug			abi_HsocketKcpDebug;

PlayStop				abi_PlayStop;
PlayPause				abi_PlayPause;
PlayNormal				abi_PlayNormal;
PlayFast				abi_PlayFast;
PlayStep				abi_PlayStep;
PlayStepSession		abi_PlayStepSession;
PlayStepNote			abi_PlayStepNote;
PlayBack				abi_PlayBack;
PlayAction				abi_PlayAction;
PlayNoStop				abi_PlayNoStop;
PlayOver				abi_PlayOver;

ReportOnline			abi_ReportOnline;
ReportOffline			abi_ReportOffline;
ReportCounter			abi_ReportCounter;
ReportApiResponse		abi_ReportApiResponse;
ReportApiSend			abi_ReportApiSend;
ReportApiRecv			abi_ReportApiRecv;
ReportOverMessage		abi_ReportOverMessage;

void 	goapi_Log(void* proto, unsigned char level, const char* log){
	abi_Log(proto, level, log);
}

long long 	goapi_Microsecond(){
	return abi_Microsecond();
}

void	goapi_UserActiveTimeOutStop(void* proto, int time){
	abi_UserActiveTimeOutStop(proto, time);
}

HSOCKET	goapi_SocketConnect(void* proto, const char* ip, int port, PROTOCOL protocol){
	return abi_SocketConnect(proto, ip, port, protocol);
}

char 	goapi_SocketSend(void* proto, HSOCKET hsock, const char* data, int len){
	return abi_SocketSend(proto, hsock, data, len);
}

char 	goapi_SocketClose(void* proto, HSOCKET hsock){
	abi_SocketClose(proto, hsock);
}

char 	goapi_PlayStop(void* proto, const char* err){
	abi_PlayStop(proto, err);
}

void 	goapi_PlayPause(void* proto){
	abi_PlayPause(proto);
}

void 	goapi_PlayNormal(void* proto){
	abi_PlayNormal(proto);
}

void 	goapi_PlayFast(void* proto, char mode){
	abi_PlayFast(proto, mode);
}

int		goapi_PlayStep(void* proto){
	return abi_PlayStep(proto);
}

int		goapi_PlayStepSession(void* proto){
	return abi_PlayStepSession(proto);
}

char* 	goapi_PlayStepNote(void* proto){
	return abi_PlayStepNote(proto);
}
void 	goapi_PlayBack(void* proto, int index){
	abi_PlayBack(proto, index);
}

char 	goapi_PlayAction(void* proto, int action){
	return abi_PlayAction(proto, action);
}
void 	goapi_PlayNoStop(void* proto){
	abi_PlayNoStop(proto);
}

int		goapi_PlayOver(void* proto){
	return abi_PlayOver(proto);
}

void 	goapi_ReportOnline(void* proto){
	abi_ReportOnline(proto);
}

void 	goapi_ReportOffline(void* proto){
	abi_ReportOffline(proto);
}

void 	goapi_ReportCounter(void* proto, const char* key, int val, int stype, int space_time){
	abi_ReportCounter(proto, key, val, stype, space_time);
}

void 	goapi_ReportApiResponse(void* proto, const char* api, int response_time){
	abi_ReportApiResponse(proto, api, response_time);
}

void 	goapi_ReportApiSend(void* proto, const char* api, int flow, int count){
	abi_ReportApiSend(proto, api, flow, count);
}

void 	goapi_ReportApiRecv(void* proto, const char* api, int flow, int count){
	abi_ReportApiRecv(proto, api, flow, count);
}

void	goapi_ReportOverMessage(void* proto, const char* msg){
	abi_ReportOverMessage(proto, msg);
}

void	goapi_HsocketPeerAddrSet(HSOCKET hsock, const char* ip, int port){

}

void	goapi_HsocketPeerAddr(HSOCKET hsock, char* ip, size_t ipsz, int* port){
	abi_HsocketPeerAddr(hsock, ip, ipsz, port);
}

void	goapi_HsocketLocalAddr(HSOCKET hsock, char* ip, size_t ipsz, int* port){
	abi_HsocketLocalAddr(hsock, ip, ipsz, port);
}

int		goapi_GetHostByName(const char* name, const char* ip, size_t ipsz){
	return abi_GetHostByName(name, ip, ipsz);
}

int		goapi_HsocketKcpCreate(HSOCKET hsock, int conv, int mode){
	return abi_HsocketKcpCreate(hsock, conv, mode);
}
void	goapi_HsocketKcpNodelay(HSOCKET hsock, int nodelay, int interval, int resend, int nc){
	abi_HsocketKcpNodelay(hsock, nodelay, interval, resend, nc);
}
void	goapi_HsocketKcpWndsize(HSOCKET hsock, int sndwnd, int rcvwnd){
	abi_HsocketKcpWndsize(hsock, sndwnd, rcvwnd);
}
int 	goapi_HsocketKcpGetConv(HSOCKET hsock){
	return abi_HsocketKcpGetConv(hsock);
}
int		goapi_HsocketKcpDebug(HSOCKET hsock, char* buf, int size){
	return abi_HsocketKcpDebug(hsock, buf, size);
}

const char*	goapi_ConfigGetString(const char* section, const char* key, const char* def){
	return abi_ConfigGetString(section, key, def);
}
int			goapi_ConfigGetNumber(const char* section, const char* key, int def){
	return abi_ConfigGetNumber(section, key, def);
}
char		goapi_ConfigGetBool(const char* section, const char* key, char def){
	return abi_ConfigGetBool(section, key, def);
}

typedef int (*func_event_start_callback)(void* user, int task_id, int user_number);
typedef int (*func_event_connect_open_callback)(void* user, const char* ip, int port, PROTOCOL type);
typedef int (*func_event_connect_made_callback)(void* user, HSOCKET hsock);
typedef int (*func_event_connect_failed_callback)(void* user, HSOCKET hsock, int err);
typedef int (*func_event_connect_send_callback)(void* user, const char* ip, int port, const char* content, int clen, PROTOCOL type);
typedef int (*func_event_connect_recved_callback)(void* user, HSOCKET hsock, const char* data, int len);
typedef int (*func_event_connect_close_callback)(void* user, const char* ip, int port, PROTOCOL type);
typedef int (*func_event_connect_closed_callback)(void* user, HSOCKET hsock, int err);
typedef int (*func_event_timeout_callback)(void* user);
typedef int (*func_event_stop_callback)(void* user, const char* errmsg);

int user_start(void* user, int task_id, int user_number){
	event_start_callback(user, task_id, user_number);
	return 0;
}
int user_open(void* user, const char* ip, int port, PROTOCOL type){
	event_connect_open_callback(user, ip, port, type);
	return 0;
}
int user_made(void* user, HSOCKET hsock){
	event_connect_made_callback(user,  hsock);
	return 0;
}
int user_failed(void* user, HSOCKET hsock, int err){
	event_connect_failed_callback(user, hsock, err);
	return 0;
}
int user_send(void* user, const char* ip, int port, const char* content, int len, PROTOCOL type){
	event_connect_send_callback(user, ip, port, content, len, type);
	return 0;
}
int user_recved(void* user, HSOCKET hsock, const char* data, int len){
	event_connect_recved_callback(user, hsock, data, len);
	return 0;
}
int user_close(void* user, const char* ip, int port, PROTOCOL type){
	event_connect_close_callback(user, ip, port, type);
	return 0;
}
int user_closed(void* user, HSOCKET hsock, int err){
	event_connect_closed_callback(user, hsock, err);
	return 0;
}
int user_timeout(void* user){
	event_timeout_callback(user);
	return 0;
}
int user_stop(void* user, const char* errmsg){
	event_stop_callback(user, errmsg);
	return 0;
}

typedef void* (*func_task_user_create)(void* user_handle, int task_id);
typedef int (*func_task_start)(int taskid, int protject_id, int machine_id, int run_number, const char* parms);
typedef int (*func_task_stop)(int taskid);

static int task_start(int taskid, int project_id, int machine_id, int run_number, const char* parms){
	Task_start_callback(taskid, project_id, machine_id, run_number, parms);
	return 0;
}
static int task_stop(int taskid){
	Task_stop_callback(taskid);
	return 0;
}
static void* task_user_create(void* user_handle, int task_id){
	void* ud = NULL;
	Task_user_create_callback(user_handle, &ud, task_id);
	return ud;
}

typedef int  (*TaskManagerRunWithBridge)(int, int, char, const char*);
typedef void (*SetTaskCallback)(func_task_user_create create, func_task_start start, func_task_stop stop);
typedef	void (*SetUserEventCallback)(func_event_start_callback start, func_event_connect_open_callback oepn, func_event_connect_made_callback made,
		func_event_connect_failed_callback failed, func_event_connect_send_callback send, func_event_connect_recved_callback recv,
		func_event_connect_close_callback close, func_event_connect_closed_callback closed, func_event_timeout_callback timeout,
		func_event_stop_callback stop);

void* so_handle = NULL;
TaskManagerRunWithBridge	task_manager_run_with_bridge = NULL;
SetTaskCallback 			set_task_callback = NULL;
SetUserEventCallback		set_user_event_callback = NULL;

int init_sheeps_so(){
	so_handle = dlopen("./libsheeps.so", RTLD_NOW);
	if (so_handle == NULL){
		printf("%s:%d %s\n", __func__, __LINE__, dlerror());
		return -1;
	}
	task_manager_run_with_bridge = (TaskManagerRunWithBridge)dlsym(so_handle, "TaskManagerRunWithBridge");
	set_task_callback = (SetTaskCallback)dlsym(so_handle, "set_task_callback");
	set_user_event_callback = (SetUserEventCallback)dlsym(so_handle, "set_user_event_callback");
	if (!task_manager_run_with_bridge || !set_task_callback || !set_user_event_callback){
		return -1;
	}

	abi_Log = (TaskUserLog)dlsym(so_handle, "TaskUserLog");
	abi_Microsecond = (Microsecond)dlsym(so_handle, "Microsecond");
	abi_UserActiveTimeOutStop = (UserActiveTimeOutStop)dlsym(so_handle, "UserActiveTimeOutStop");
	abi_SocketConnect = (SocketConnect)dlsym(so_handle, "SocketConnect");
	abi_SocketSend = (SocketSend)dlsym(so_handle, "SocketSend");
	abi_SocketClose = (SocketClose)dlsym(so_handle, "SocketClose");

	abi_PlayStop = (PlayStop)dlsym(so_handle, "PlayStop");
	abi_PlayPause = (PlayPause)dlsym(so_handle, "PlayPause");
	abi_PlayNormal = (PlayNormal)dlsym(so_handle, "PlayNormal");
	abi_PlayFast = (PlayFast)dlsym(so_handle, "PlayFast");
	abi_PlayStep = (PlayStep)dlsym(so_handle, "PlayStep");
	abi_PlayStepSession = (PlayStepSession)dlsym(so_handle, "PlayStepSession");
	abi_PlayStepNote = (PlayStepNote)dlsym(so_handle, "PlayStepNote");
	abi_PlayBack = (PlayBack)dlsym(so_handle, "PlayBack");
	abi_PlayAction = (PlayAction)dlsym(so_handle, "PlayAction");
	abi_PlayNoStop = (PlayNoStop)dlsym(so_handle, "PlayNoStop");
	abi_PlayOver = (PlayOver)dlsym(so_handle, "PlayOver");

	abi_ReportOnline = (ReportOnline)dlsym(so_handle, "ReportOnline");
	abi_ReportOffline = (ReportOffline)dlsym(so_handle, "ReportOffline");
	abi_ReportCounter = (ReportCounter)dlsym(so_handle, "ReportCounter");
	abi_ReportApiResponse = (ReportApiResponse)dlsym(so_handle, "ReportApiResponse");
	abi_ReportApiSend = (ReportApiSend)dlsym(so_handle, "ReportApiSend");
	abi_ReportApiRecv = (ReportApiRecv)dlsym(so_handle, "ReportApiRecv");
	abi_ReportOverMessage = (ReportOverMessage)dlsym(so_handle, "ReportOverMessage");

	abi_HsocketPeerAddr = (HsocketPeerAddr)dlsym(so_handle, "HsocketPeerAddr");
	abi_HsocketPeerAddrSet = (HsocketPeerAddrSet)dlsym(so_handle, "HsocketPeerAddrSet");
	abi_HsocketLocalAddr = (HsocketLocalAddr)dlsym(so_handle, "HsocketLocalAddr");
	abi_GetHostByName = (GetHostByName)dlsym(so_handle, "GetHostByName");

	abi_HsocketKcpCreate = (HsocketKcpCreate)dlsym(so_handle, "HsocketKcpCreate");
	abi_HsocketKcpNodelay = (HsocketKcpNodelay)dlsym(so_handle, "HsocketKcpNodelay");
	abi_HsocketKcpWndsize= (HsocketKcpWndsize)dlsym(so_handle, "HsocketKcpWndsize");
	abi_HsocketKcpDebug = (HsocketKcpDebug)dlsym(so_handle, "HsocketKcpDebug");

	abi_ConfigGetString = (ConfigGetString)dlsym(so_handle, "config_get_string_value");
	abi_ConfigGetNumber = (ConfigGetNumber)dlsym(so_handle, "config_get_number_value");
	abi_ConfigGetBool = (ConfigGetBool)dlsym(so_handle, "config_get_bool_value");
	return 0;
}

int run_sheeps_so(int project_id, int group_id, char server, const char* config_file){
	set_task_callback(task_user_create, task_start, task_stop);
	set_user_event_callback(user_start, user_open, user_made, user_failed, user_send, user_recved, user_close, user_closed, user_timeout, user_stop);
	task_manager_run_with_bridge(project_id, group_id, server, config_file);
	return 0;
}
#endif
*/
import "C"
